/*
   Copyright (c) [Year] [name of copyright holder]
   [Software Name] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.  
*/

#ifndef JIAJIA_JJLOG_HPP
#define JIAJIA_JJLOG_HPP

#include"jiajiastd.hpp"

namespace jiajia{

    class jjlog{
    private:
        std::deque<std::string> mStrStack;
        std::deque<int> mLevelStack;
        unsigned int mLevel;
        std::ostream * os;
        
    public:
        jjlog(): mStrStack(), mLevelStack(), mLevel(0), os(&std::cout){}

        template<typename T>
        jjlog & out(const T v){
            using typeopseq = my::typeOp<char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long>;
            static_assert(typeopseq::func_include<T>::value);
            (*os)<<v;
            return *this;
        }

        template<typename T>
        jjlog & out(const T * pt){
            (*os)<<(void *)pt;
            return *this;
        }

        jjlog & out(const std::string & str){
            (*os)<<str;
            return *this;
        }

        jjlog & err(const std::string & str){
            mStrStack.push_back(str);
            mLevelStack.push_back(mLevel);
            return *this;
        }

        jjlog & err(std::string && str){
            mStrStack.push_back(std::move(str));
            mLevelStack.push_back(mLevel);
            return *this;
        }

        jjlog & endl(){
            ++mLevel;
            return *this;
        }

        jjlog & errend(){
            while(!mStrStack.empty()){
                for(unsigned int i = 0; i < mLevel - mLevelStack.back(); ++i)
                    (*os)<<'\t';
                (*os)<<mStrStack.back()<<std::endl;
                mStrStack.pop_back();
                mLevelStack.pop_back();
            }
            return *this;
        }
    };

    static jjlog log;
}

#endif
